package download

import (
	"context"
	"crypto/tls"
	"fmt"
	"github.com/cenkalti/backoff/v4"
	"github.com/levigross/grequests"
	"net"
	"net/http"
	"sync"
	"time"
	"ts-downloader/log"
)

var (
	httpCli     *http.Client
	onceHttpCli sync.Once
)

func getHttpClient() *http.Client {
	onceHttpCli.Do(func() {
		httpCli = &http.Client{
			Transport: &http.Transport{
				DialContext: (&net.Dialer{
					Timeout:   time.Second * 5,
					KeepAlive: time.Second * 30,
				}).DialContext,
				TLSClientConfig: &tls.Config{
					InsecureSkipVerify: true,
				},
				TLSHandshakeTimeout:   time.Second * 5,
				DisableCompression:    false,
				MaxIdleConns:          50,
				MaxIdleConnsPerHost:   10,
				MaxConnsPerHost:       20,
				IdleConnTimeout:       time.Second * 60,
				ResponseHeaderTimeout: time.Second * 10,
			},
			Timeout: time.Second * 30,
		}
	})
	return httpCli
}

func DoGetRequest(ctx context.Context, u string, retry uint64) (*grequests.Response, error) {
	operationFun := func() (*grequests.Response, error) {
		res, err := grequests.Get(u, &grequests.RequestOptions{HTTPClient: getHttpClient(), Context: ctx})
		if err != nil {
			return res, err
		}
		if !res.Ok {
			return res, fmt.Errorf("%d", res.StatusCode)
		}
		return res, err
	}
	return backoff.RetryNotifyWithData[*grequests.Response](operationFun, backoff.WithContext(backoff.WithMaxRetries(backoff.NewExponentialBackOff(), retry), ctx), func(err error, duration time.Duration) {
		log.Error("Do request [%s] err = %v, duration = %v", u, err, duration)
	})
}
